//
//  AppFunctionHelper.swift
//  XiaoweHealthy
//
//  Created by Riven on 2022/8/10.
//

import Foundation
import AVFAudio
import AudioToolbox

func simpleSynchronized(lock: AnyObject, closure: () -> Void) {
    objc_sync_enter(lock)
    closure()
    objc_sync_exit(lock)
}

extension Equatable {
    
    func isEqualIn<T: Equatable>(_ list: [T]) -> Bool {
        guard let st = self as? T else {
            return false
        }
        
        for i in list {
            if i == st {
                return true
            }
        }
        
        return false
    }
    
}

extension AppFunctionHelper {
    
    /// 获取当前时间戳
    class func getCurrentTimeInterval() -> TimeInterval {
        Date().timeIntervalSince1970
    }
    
    // 将数值 x 在 [min, max] 范围内进行反转
    class func reverseValueInRange(_ x: Int, min: Int, max: Int) -> Int {
        let tArray = stride(from: min, through: max, by: 1)
        guard let fIndex = tArray.first(where: { $0 == x }) else {
            return x
        }
        
        let rArray = tArray.reversed()
        return rArray[fIndex]
    }
//    class func reverseValueInRange<T: FloatingPoint>(_ x: T, min: T, max: T) -> T {
//        let center = (min + max) / 2
//        return center - (x - center)
//    }
    
    class func oneArrayContainsOtherArrayAllElement<Element: Equatable>(one: [Element], other: [Element]) -> Bool {
        if one.count < other.count {
            return false
        }
        
        for i in other {
            let isOk = one.contains(where: { $0 == i })
            if !isOk {
                return false
            }
        }
        
        return true
    }
    
}

class AppFunctionHelper {
    
    class func getLocalLanguage() -> String {
        let preferredLanguages = Locale.preferredLanguages
        return preferredLanguages.first ?? ""
//        return Locale.current.languageCode ?? ""
    }
    
    /// 获取系统首选的主要语言（如 "zh"、"en"）
    class func getLocalPrimaryLanguage() -> String {
        guard let firstLanguage = Locale.preferredLanguages.first else {
            return "en"
        }
        // 截取主要语言代码（如从 "zh-Hans-CN" 中提取 "zh"）
        // 使用示例
//        if let primaryLang = getPrimaryLanguage() {
//            print("主要语言：\(primaryLang)")
//        }
//
//        switch primaryLang {
//        case "zh":
//            print("当前为中文环境")
//        case "en":
//            print("当前为英文环境")
//        default:
//            print("其他语言环境：\(primaryLang)")
//        }
        let primary = firstLanguage.components(separatedBy: "-").first
        return primary ?? "en"
    }
    
    // MARK: - HTTP 语言编码
    class func getHttpHeaderAcceptLanguage() -> String {
        getLocalLanguage()
    }
    
    class func getReplacingOccurrencesString(from: String, key: String, value: String) -> String {
        return from.replacingOccurrences(of: key, with: value)
    }
    
    // MARK: - Version Compare
    class func versionCompare(preVersion: String, nextVersion: String) -> ComparisonResult {
        let preVersion = preVersion.replacingOccurrences(of: "V", with: "", options: .caseInsensitive)
        let nextVersion = nextVersion.replacingOccurrences(of: "V", with: "", options: .caseInsensitive)
        
        let preArray = preVersion.components(separatedBy: ".")
        let nextArray = nextVersion.components(separatedBy: ".")
        
        var ret: ComparisonResult = .orderedSame
        
        let minCount = min(preArray.count, nextArray.count)
        
        if minCount > 0 {
            for i in 0..<minCount {
                guard let iPre = Int(preArray[i]), let iNext = Int(nextArray[i]) else {
                    ret = .orderedSame
                    break
                }
                
                if iPre < iNext {
                    ret = .orderedAscending
                    break
                } else if iPre > iNext {
                    ret = .orderedDescending
                    break
                }
            }
            
            if ret == .orderedSame {
                if preArray.count > nextArray.count {
                    ret = .orderedAscending
                } else if preArray.count < nextArray.count {
                    ret = .orderedAscending
                }
            }
        } else {
            if preArray.count > nextArray.count {
                ret = .orderedDescending
            } else if preArray.count == nextArray.count {
                ret = .orderedSame
            } else {
                ret = .orderedAscending
            }
        }
        
        log.info("versionCompare, ret = \(ret), preArray = \(preArray), nextArray = \(nextArray)")

        return ret
    }
    
    
    // MARK: -
    static func isValidPhoneNum(_ phoneNum: String) -> Bool {
        let lang = AppFunctionHelper.getLocalPrimaryLanguage()
        if lang != "zh" {
            return true
        }
        
        if phoneNum.count != 11 {
            return false
        }
        guard let fNum = phoneNum.first, fNum == "1" else {
            return false
        }
        
        return true
    }
    
    static func getSecretPhoneNum(with phoneNum: String) -> String {
        if phoneNum.count != 11 {
            return phoneNum
        }
        
//        var sPhoneText = phoneNum.substring(from: 0, length: 3) ?? ""
//        sPhoneText += "******"
//        sPhoneText += phoneNum.suffix(2)
        
        let startIndex = phoneNum.index(phoneNum.startIndex, offsetBy: 3)
        let endIndex = phoneNum.index(phoneNum.startIndex, offsetBy: 8)
        let sPhoneNum = phoneNum.replacingCharacters(in: startIndex ... endIndex, with: "******")
        
        return sPhoneNum
    }
    
    /// 前3后4
    static func getSecretPhoneNumPrefix_3_suffix_4(with phoneNum: String) -> String {
        if phoneNum.count != 11 {
            return phoneNum
        }
        
//        var sPhoneText = phoneNum.substring(from: 0, length: 3) ?? ""
//        sPhoneText += "******"
//        sPhoneText += phoneNum.suffix(2)
        
        let startIndex = phoneNum.index(phoneNum.startIndex, offsetBy: 3)
        let endIndex = phoneNum.index(phoneNum.startIndex, offsetBy: 6)
        let sPhoneNum = phoneNum.replacingCharacters(in: startIndex ... endIndex, with: "****")
        
        return sPhoneNum
    }
    
    // MARK: - Mac
    class func getColonMac(withoutColonMac: String) -> String {
        let macStr = withoutColonMac.replacingOccurrences(of: ":", with: "")
        
//        let startIndex = 6
        let macAddrLength = 12
//        let startIndex = 0
//        let endIndex = startIndex + macAddrLength
        
        var retMac = ""
        
        log.info("macStr = \(macStr)")
        guard macStr.count == macAddrLength else {
            log.error("解析 getColonMac Mac 错误, 超出界限")
            return retMac
        }
        
        
        var macStringArray = [String]()
        for i in stride(from: 0, to: macAddrLength, by: 2) {
            if let tMacSubString = macStr[i...(i+1)] {
                macStringArray.append(String(tMacSubString))
            }
        }
        
        retMac = macStringArray.joined(separator: ":")
        
        return retMac
    }
    
    /*
     Mac地址上报规则
     原相和天籁系列 20:24:05:11:02:E4
     o平台只有左耳L20:24:05:11:02:E4
     o平台只有右耳R20:24:05:11:02:E4
     o平台双耳情况R20:24:05:11:02:E4|L20:24:05:11:02:E4
     */
    /// 获取合并的mac
    /// - Parameters:
    ///     - leftMac: 左耳的mac地址,
    ///     - rightMac: 右耳的mac地址
    /// - Returns: 合并后的Mac地址
    class func getMergeMac(leftMac: String, rightMac: String) -> String {
        var retMac = ""
        if !leftMac.isEmpty, !rightMac.isEmpty {
            if leftMac.compare(rightMac, options: .caseInsensitive) == .orderedSame {
                retMac = leftMac
            } else {
                retMac = "R\(rightMac)|L\(leftMac)"
            }
        } else if !leftMac.isEmpty {
            retMac = "L\(leftMac)"
        } else if !rightMac.isEmpty {
            retMac = "R\(rightMac)"
        }
        
        return retMac
    }
    
    /// 获取分离的mac
    /// - Parameters:
    ///     - mergeMac: 合并的mac
    /// - Returns: (leftMac: String, rightMac: String)合分离的mac
    class func getSeparateMac(mergeMac: String) -> (leftMac: String, rightMac: String) {
        var leftMac = ""
        var rightMac = ""
        let macArray = mergeMac.components(separatedBy: "|")
        for iMac in macArray {
            if iMac.hasPrefix("L") {
                leftMac = iMac.replacingOccurrences(of: "L", with: "")
                continue
            } else if iMac.hasPrefix("R") {
                rightMac = iMac.replacingOccurrences(of: "R", with: "")
                continue
            } else {
                leftMac = iMac
                rightMac = iMac
                break
            }
        }
        return (leftMac, rightMac)
    }
    
    class func getDevicePort(mergeMac: String) -> XWDevicePortType {
        var retType: XWDevicePortType = .none
        let (leftMac, rightMac) = AppFunctionHelper.getSeparateMac(mergeMac: mergeMac)
        if !leftMac.isEmpty, !rightMac.isEmpty {
            retType = .none
        } else if !leftMac.isEmpty {
            retType = .left
        } else if !rightMac.isEmpty {
            retType = .right
        }

        return retType
    }
    
    // MARK: -
    class func getShortFreqBandText(freqBand: Int, isReplaceZeroFreq: Bool = true) -> String {
        var tText = ""
        if freqBand == 0 {
            if isReplaceZeroFreq {
                tText = "125"
            } else {
                tText = "0"
            }
        } else if freqBand >= 1000 {
            tText = (freqBand.double / 1000).getCleanZerFormattedString(maximumFractionDigits: 3) + "k"
            tText = tText.replacingOccurrences(of: "0", with: "")
        } else {
            tText = freqBand.string
        }
        
        return tText
    }
    
    // MARK: -
    /// 天时分
//    class func getDHMTextWithTime(_ timeValue: Int) -> String {
//        if timeValue < 0 {
//            return ""
//        }
//        
//        let days = timeValue / (24 * 3600)
//        let hours = (timeValue / 3600) % 24
//        let minutes = (timeValue / 60) % 60
//        
//        if days == 0, hours == 0 {
//            return "\(minutes)分"
//        } else if days == 0 {
//            return "\(hours)时\(minutes)分"
//        } else {
//            return "\(days)天\(hours)时\(minutes)分"
//        }
//    }
    
    class func getHMTextWithTime(_ timeValue: Int) -> String {
        if timeValue < 0 {
            return ""
        }
        
        let hours = (timeValue / 3600)
        let minutes = (timeValue / 60) % 60
        
//        if days == 0, hours == 0 {
//            
//        } else if days == 0 {
//            return "\(hours)时\(minutes)分"
//        } else {
//            return "\(days)天\(hours)时\(minutes)分"
//        }
        return "\(hours)小时\(minutes)分钟"
    }
    
    /// 00:00:00 (时分秒)
    class func getHMSTextWithTime(_ timeValue: Int) -> String {
        if timeValue < 0 {
            return "00:00:00"
        }
        
        let hours = (timeValue / 3600) % 24
        let minutes = (timeValue / 60) % 60
        let seconds = timeValue % 60
        
        return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
    }
    
    // 核心处理逻辑
    class func getCountFromTextChange(currentText: String, range: NSRange, replacementString: String) -> Int {
        // 将当前文本转换为NSString，便于处理NSRange
        let nsText = currentText as NSString
        // 计算替换后的文本
        let newText = nsText.replacingCharacters(in: range, with: replacementString)
        
        // 计算新文本中的中文字符数量
        let chineseCount = countChineseCharacters(in: newText)
        
        // 如果超过限制，不允许输入
        return chineseCount
    }
    
    // 计算字符串中的中文字符数量
    class func countChineseCharacters(in string: String) -> Int {
        var count = 0
        for scalar in string.unicodeScalars {
            // 中文字符的Unicode范围：\u4e00-\u9fff
            if scalar.value >= 0x4e00 && scalar.value <= 0x9fff {
                count += 1
            }
        }
        return count
    }
    
}

// MARK: - 线程切换 延时处理
extension AppFunctionHelper {
    
    class func executeInMainThread(_ completion: @escaping (() -> Void)) {
        DispatchQueue.main.async(execute: completion)
    }
    
    /// 主线程延时处理
    class func mainQueueAsyncAfter(delay: Double, completion: @escaping (() -> Void)) {
        DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: completion)
    }
    
    /// 主线程延时处理
    class func mainQueueAsyncAfter(delay: Double, atVC: UIViewController, completion: @escaping (() -> Void)) {
        atVC.view.isUserInteractionEnabled = false
        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
            atVC.view.isUserInteractionEnabled = true
            completion()
        }
    }
    
}

// MARK: - App Icon
extension AppFunctionHelper {
    
    class func getLastAppIcon() -> UIImage? {
        guard let iconsDictionary = Bundle.main.infoDictionary?["CFBundleIcons"] as? [String: Any],
              let primaryIconsDictionary = iconsDictionary["CFBundlePrimaryIcon"] as? [String: Any],
              let iconFiles = primaryIconsDictionary["CFBundleIconFiles"] as? [String],
              let lastIcon = iconFiles.last else {
            return nil
        }
        
        return UIImage(named: lastIcon)
    }
    
}

// MARK: -
extension AppFunctionHelper {
    
    /**
     启动图无法实时更换或显示空白页
     对于这个问题，要把启动页用到的图片资源放在项目文件目录中，不要放在imageAsset中。
     还有一种我自测时候发现的情况，部分带刘海机型就算放在项目文件目录中，还是无法实时更换。
     查阅了资料有说每次更换启动图时都要修改图片名，或者删除storyboard，clean项目等，但亲测这些方法无法有效解决该问题，唯一有效的是删除重装app，但显然你不能要求用户这么做。
     最后google到了一篇文章， 原来apple会对launchScreen.storyboard 启动的app，部分机型会缓存一份启动图截放在沙盒目录 /Library/SplashBoard 中，每次启动会优先读取缓存，造成启动图无法及时更新。所以决定在app每次启动后有缓存就清除缓存。
     清除缓存的调用时机需要自己把握，为了每次都被调用到，我是在app启动后的中间页做的该操作

     作者：热心市民白先生
     链接：https://juejin.cn/post/6844904047435055118
     来源：稀土掘金
     著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
     */
    /// 为了每次都读取最新的启动图，所以要在有缓存的时候清除缓，
    class func removeLaunchScreenCacheIfNeeded() {
        // 构建SplashBoard缓存路径
        let homeDirectory = NSHomeDirectory()
        let filePath = "\(homeDirectory)/Library/SplashBoard"
        
        let fileManager = FileManager.default
        
        // 检查路径是否存在
        if fileManager.fileExists(atPath: filePath) {
            do {
                // 尝试删除缓存
                try fileManager.removeItem(atPath: filePath)
                print("清除LaunchScreen缓存成功")
            } catch {
                print("清除LaunchScreen缓存失败: \(error.localizedDescription)")
            }
        }
    }
    
}

// MARK: - AVAudioSession Active
extension AppFunctionHelper {
    
    class func setAVAudioSessionActive() {
        try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
        try? AVAudioSession.sharedInstance().setActive(true)
    }
    
    /// 震动
    class func vibrate() {
        AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)
//        UIDevice.jk.systemSoundIDShock(type: .short3DPopHomeVibration)
    }
    
}


// MARK: -
extension AppFunctionHelper {
    
    // 联系客服（联系验配师）
    class func gotoContactFitter(targetVC: UIViewController) {
        let isOk = AppOpenUrlManager.gotoWeixin()
        if !isOk {
            targetVC.view.makeToast("请安装微信")
        }        
    }
    
    // 添加验配师
    class func gotoAddFitter(inView: UIView) {
        let isOk = addFitter()
        if !isOk {
            inView.makeToast("请安装微信")
        }
    }
    
    // 添加验配师
    class func addFitter() -> Bool {
        let urlPath = "weixin://biz/ww/profile/https%3A%2F%2Fwork.weixin.qq.com%2Fca%2Fcawcde853429d8f9db%3Fcustomer_channel%3DWORK"
        guard let url = URL(string: urlPath) else {
            log.error("跳转微信失败 url 为空 \n")
            
            return false
        }
        
        let isOk = UIApplication.shared.canOpenURL(url)
        
        if !isOk {
            log.error("跳转微信失败 url = \(url) \n")
            
            return false
        }
        
        UIApplication.shared.open(url)
        
        return true
    }
    
}
